/**
  ******************************************************************************
  * @file    usart.c
  * @author  Puya Application Team
  * @brief   Contains USART HW configuration
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 Puya Semiconductor.
  * All rights reserved.</center></h2>
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "wdg.h"

/* Private define ------------------------------------------------------------*/
#define SYS_CLK                           24000000U
#define MAX_BAUDRATE                      (1000000+100)
#define MIN_BAUDRATE                      (1200-100)
#define DEFAULT_BAUDRATE                  115200            /* Default Baudrate */
#define MAX_BRR                           ((SYS_CLK+MAX_BAUDRATE/2)/MAX_BAUDRATE)
#define MIN_BRR                           ((SYS_CLK+MIN_BAUDRATE/2)/MIN_BAUDRATE)
#define DEFAULT_BRR                       ((SYS_CLK+DEFAULT_BAUDRATE/2)/DEFAULT_BAUDRATE)

/*
****AT32F425C8T7****AT32F415KBU7****
USART1 PA9：USART1_TX PA10：USART1_RX
USART2 PA2：USART2_TX PA3：USART2_RX

****AT32F425C8T7****
USART0 (PA9 and PA10)，USART1 (PA2 and PA3, PA14 and PA15)

****PY32F410****
USART1 (PA9 and PA10)，UART1 (PA2 and PA3, PA14 and PA15)
*/

#define UART_DIV_SAMPLING16(_PCLK_, _BAUD_)            (((_PCLK_)*25U)/(4U*(_BAUD_)))
#define UART_DIVMANT_SAMPLING16(_PCLK_, _BAUD_)        (UART_DIV_SAMPLING16((_PCLK_), (_BAUD_))/100U)
#define UART_DIVFRAQ_SAMPLING16(_PCLK_, _BAUD_)        (((UART_DIV_SAMPLING16((_PCLK_), (_BAUD_)) - (UART_DIVMANT_SAMPLING16((_PCLK_), (_BAUD_)) * 100U)) * 16U + 50U) / 100U)
/* UART BRR = mantissa + overflow + fraction
             = (UART DIVMANT << 4) + (UART DIVFRAQ & 0xF0) + (UART DIVFRAQ & 0x0FU) */
#define UART_BRR_SAMPLING16(_PCLK_, _BAUD_)            (((UART_DIVMANT_SAMPLING16((_PCLK_), (_BAUD_)) << 4U) + \
                                                        (UART_DIVFRAQ_SAMPLING16((_PCLK_), (_BAUD_)) & 0xF0U)) + \
                                                        (UART_DIVFRAQ_SAMPLING16((_PCLK_), (_BAUD_)) & 0x0FU))
                                                        
/* Private types ------------------------------------------------------------*/
typedef enum _INTERFACE
{
  INTERFACE_USART1 = 0,
  INTERFACE_UART1,
} INTERFACE;

INTERFACE guc_InterfaceDetection;
/* Exported functions --------------------------------------------------------*/
/**
  * @brief  Initialize Bootloader.
  * @param  None.
  * @retval None.
  */
void USART_Init(void)
{
  uint64_t integer = 0;
  uint32_t dwRstPALevel[3][2];

#if 1//轮询检查RX(PA3,PA10,PA15)是否接收到START信号(低电平)
  SET_BIT(RCC->AHBENR, RCC_AHBENR_IOPAEN);

  CLEAR_BIT(GPIOA->MODER, GPIO_MODER_MODE3|GPIO_MODER_MODE10|GPIO_MODER_MODE15);

  SET_BIT(GPIOA->PUPDR, GPIO_PUPDR_PUPD3_0|GPIO_PUPDR_PUPD10_0|GPIO_PUPDR_PUPD15_0); //增加上拉配置

  dwRstPALevel[0][0] = READ_BIT(GPIOA->IDR, GPIO_IDR_ID3);
  dwRstPALevel[1][0] = READ_BIT(GPIOA->IDR, GPIO_IDR_ID10);
  dwRstPALevel[2][0] = READ_BIT(GPIOA->IDR, GPIO_IDR_ID15);

  while (1)
  {
    WDG_Refresh();
    
    dwRstPALevel[0][1] = dwRstPALevel[0][0];
    dwRstPALevel[1][1] = dwRstPALevel[1][0];
    dwRstPALevel[2][1] = dwRstPALevel[2][0];
    dwRstPALevel[0][0] = READ_BIT(GPIOA->IDR, GPIO_IDR_ID3);
    dwRstPALevel[1][0] = READ_BIT(GPIOA->IDR, GPIO_IDR_ID10);
    dwRstPALevel[2][0] = READ_BIT(GPIOA->IDR, GPIO_IDR_ID15);
    
    if (dwRstPALevel[0][1] && (!dwRstPALevel[0][0]))
    {
      guc_InterfaceDetection = INTERFACE_UART1;
      MODIFY_REG(GPIOA->MODER, (GPIO_MODER_MODE2|GPIO_MODER_MODE3), (GPIO_MODER_MODE2_1|GPIO_MODER_MODE3_1));//10: 复用功能模式
      //1101:AF13 UART1_TX(PA2) UART1_RX(PA3)
      SET_BIT(GPIOA->AFR[0], (GPIO_AFRL_AFSEL2|GPIO_AFRL_AFSEL3));
      CLEAR_BIT(GPIOA->AFR[0], (GPIO_AFRL_AFSEL2_1|GPIO_AFRL_AFSEL3_1));
      break;
    }
    if (dwRstPALevel[1][1] && (!dwRstPALevel[1][0]))
    {
      guc_InterfaceDetection = INTERFACE_USART1;
      MODIFY_REG(GPIOA->MODER, (GPIO_MODER_MODE9|GPIO_MODER_MODE10), (GPIO_MODER_MODE9_1|GPIO_MODER_MODE10_1));//10: 复用功能模式
      //1101:AF13 USART1_TX(PA9) USART1_RX(PA10)
      SET_BIT(GPIOA->AFR[1], (GPIO_AFRH_AFSEL9|GPIO_AFRH_AFSEL10));
      CLEAR_BIT(GPIOA->AFR[1], (GPIO_AFRH_AFSEL9_1|GPIO_AFRH_AFSEL10_1));
      break;
    }
    if (dwRstPALevel[2][1] && (!dwRstPALevel[2][0]))
    {
      guc_InterfaceDetection = INTERFACE_UART1;
      MODIFY_REG(GPIOA->MODER, (GPIO_MODER_MODE14|GPIO_MODER_MODE15), (GPIO_MODER_MODE14_1|GPIO_MODER_MODE15_1));//10: 复用功能模式
      //1101:AF13 UART1_TX(PA14) USART1_RX(PA15)
      SET_BIT(GPIOA->AFR[1], (GPIO_AFRH_AFSEL14|GPIO_AFRH_AFSEL15));
      CLEAR_BIT(GPIOA->AFR[1], (GPIO_AFRH_AFSEL14_1|GPIO_AFRH_AFSEL15_1));
      break;
    }
  }
#endif

  if (INTERFACE_USART1 == guc_InterfaceDetection)
  {
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN);

    //USART_CR1_M1M0  1： 1 start bit， 9 data bit， n stop bit
    //USART_CR1_PCE  1：奇偶校验使能
    //USART_CR1_PS  0：偶校验(EVEN)
    //USART_CR2_STOP 00： 1 stop bit
    SET_BIT(USART1->CR1, (USART_CR1_M0|USART_CR1_PCE));

    WRITE_REG(USART1->BRR, DEFAULT_BRR);

    SET_BIT(USART1->CR1, USART_CR1_UE);//1： USART 使能

    //USART_CR3_ABRMOD 00：从 start 位开始测量波特率
    //USART_CR3_ABREN 1：自动波特率使能
//    MODIFY_REG(USART1->CR3, USART_CR3_ABRMOD, USART_CR3_ABREN);

    SET_BIT(USART1->CR1, USART_CR1_RE); //1： 接收使能
    
    while (0x7F != (uint8_t)(READ_BIT(USART1->DR, USART_DR_DR) & 0xFFU))
    {
      WDG_Refresh();
      
//      SET_BIT(USART1->SR, USART_SR_ABRRQ);
    }
    
//    CLEAR_BIT(USART1->CR3, USART_CR3_ABREN);
    
    SET_BIT(USART1->CR1, USART_CR1_TE); //1： 传送使能
  }
  else
  {
    SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART1EN);

    //UART_CR1_M  0x3（CHAR_8BITS）：每个字符8个数据位
    //UART_CR1_PCE  0x1（ENABLED）：启用奇偶校验
    //UART_CR1_PS  0x1（EVEN_PRITY） ：偶校验
    //UART_CR1_STOP 0x0（STOP_1BIT）：1个停止位
    SET_BIT(UART1->CR1, (UART_CR1_M|UART_CR1_PCE|UART_CR1_PS));

    integer = UART_BRR_SAMPLING16(SYS_CLK, DEFAULT_BAUDRATE);
    MODIFY_REG(UART1->BRR,  UART_BRR_BRR,   ((integer >> 4) & 0xFFFF));
    MODIFY_REG(UART1->BRRF, UART_BRRF_BRRF, (integer & 0xF));
    
    while (0x7F != (uint8_t)(READ_BIT(UART1->DR, UART_DR_DR) & 0xFFU))
    {
      WDG_Refresh();
    }
  }
}

/**
  * @brief  This function is used to send one byte through USART pipe.
  * @param  ucDataBuf The byte to be sent.
  * @retval None.
  */
void USART_SendByte(uint8_t ucDataBuf)
{
  if (INTERFACE_USART1 == guc_InterfaceDetection)
  {
    USART1->DR = (ucDataBuf & 0xFFU);
    while (USART_SR_TC != READ_BIT(USART1->SR, USART_SR_TC))
    {
      WDG_Refresh();
    }
    CLEAR_BIT(USART1->SR, USART_SR_TC);
  }
  else
  {
    UART1->DR = (ucDataBuf & 0xFFU);
    while (UART_SR_TXE != READ_BIT(UART1->SR, UART_SR_TXE))
    {
      WDG_Refresh();
    }
    CLEAR_BIT(UART1->SR, UART_SR_TXE);
  }
}

/**
  * @brief  This function is used to read one byte from USART pipe.
  * @retval Returns the read byte.
  */
uint8_t USART_ReadByte(void)
{
  if (INTERFACE_USART1 == guc_InterfaceDetection)
  {
    while (USART_SR_RXNE != READ_BIT(USART1->SR, USART_SR_RXNE))
    {
      WDG_Refresh();
    }
    return (uint8_t)(READ_BIT(USART1->DR, USART_DR_DR) & 0xFFU);
  }
  else
  {
    while (UART_SR_RXNE != READ_BIT(UART1->SR, UART_SR_RXNE))
    {
      WDG_Refresh();
    }
    return (uint8_t)(READ_BIT(UART1->DR, UART_DR_DR) & 0xFFU);
  }
}

#ifdef _DEBUG
//重定向c库函数printf到串口DEBUG_USART，重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
  /* 发送一个字节数据到串口DEBUG_USART */
  USART_SendByte(ch);

  return (ch);
}
#endif
